class GPSecurityDomain
  attr_accessor :secure_channel
  
  def initialize card,crypto
    @crypto = crypto
    @card = card
  end
  
  #
  #
  #
  def open_secure_channel security_domain = ByteString.new('a000000003000000',HEX)
    @secure_channel = GPScp02.new(@card,@crypto)
    @secure_channel.initialize_update security_domain
    @secure_channel.external_authenticate
  end
  
  
  #
  #
  #
  def delete_aid aid
    if @secure_channel.state == :SC_OPEN
      @card.delete aid 
    else
      puts ">> please open secure channel"
    end  
  end
  
  #
  #
  #
  def install_for_install_and_selectable data
    if @secure_channel.state == :SC_OPEN
      @card.install_for_install data 
    else
      puts ">> please open secure channel"
    end 
  end
   
  #
  #
  #
  def store_data dgi,block_number,flag=:DGI
    p1 = 0x00
    case flag
      when :DGI
        p1 = 0x00
      when :LAST_DGI
        p1 = 0x80
    end      
    res,sw = @card.sendApdu(0x80, 0xE2, p1, block_number, dgi)
    assert(sw == ByteString.new('9000',HEX),"Store data error")
  end
  
  #
  #
  #
  def store_encrypted_data meth,dgi,block_number,tk=nil
    tlvlist = TLVList.new(dgi,TLV.DGI)
    tlv = tlvlist.index(0);
    v = tlv.getValue
    v = @crypto.decrypt(tk,Crypto.DES_ECB,v) if tk
    v = @secure_channel.encryptDek v,meth
    tlv.data = v.getBytes
    res,sw = @card.sendApdu(0x80, 0xE2, 0x60, block_number, tlv.getTLV)
    assert(sw == ByteString.new('9000',HEX),"Store data error")
  end
  #
  #
  #
  def change_kmc_to_kmu kmu_value,key_version = ByteString.new("01", HEX)
    kmu = Key.new
    kmu.setComponent(Key.DES, kmu_value)
    #get kmu_enc from KMU
    kmu_enc = @crypto.get_derive_key(kmu, @secure_channel.public_derive_factor, ByteString.new("F001", HEX), ByteString.new("0F01", HEX))
    wrapped_kmu_enc = Key.new
    @crypto.wrap(@secure_channel.dek_session_key, Crypto.DES_ECB, kmu_enc, wrapped_kmu_enc);
    kmu_enc_kcv = @crypto.kcv_of kmu_enc
    #get kmu_mac from KMU
    kmu_mac = @crypto.get_derive_key(kmu, @secure_channel.public_derive_factor, ByteString.new("F002", HEX), ByteString.new("0F02", HEX))
    wrapped_kmu_mac = Key.new
    @crypto.wrap(@secure_channel.dek_session_key, Crypto.DES_ECB, kmu_mac, wrapped_kmu_mac);
    kmu_mac_kcv = @crypto.kcv_of kmu_mac
    #get kmu_kek from KMU
    kmu_kek = @crypto.get_derive_key(kmu, @secure_channel.public_derive_factor, ByteString.new("F003", HEX), ByteString.new("0F03", HEX))
    wrapped_kmu_kek = Key.new
    @crypto.wrap(@secure_channel.dek_session_key, Crypto.DES_ECB, kmu_kek, wrapped_kmu_kek);
    kmu_kek_kcv = @crypto.kcv_of kmu_kek
    # Algorithm ID 3DES key
    alg_id = ByteString.new("80", HEX);
    key_len = ByteString.new("10", HEX);
    kcv_len = ByteString.new("03", HEX);
    
    put_key = key_version.concat(alg_id).concat(key_len).concat(wrapped_kmu_enc.getComponent(Key.DES)).concat(kcv_len).concat(kmu_enc_kcv)
    put_key = put_key.concat(alg_id).concat(key_len).concat(wrapped_kmu_mac.getComponent(Key.DES)).concat(kcv_len).concat(kmu_mac_kcv)
    put_key = put_key.concat(alg_id).concat(key_len).concat(wrapped_kmu_kek.getComponent(Key.DES)).concat(kcv_len).concat(kmu_kek_kcv)
    #@card.sendApdu 0x80, 0xD8, 0x01, 0x81, put_key
    @card.sendApdu 0x80, 0xD8, 0x00, 0x81, put_key
  end
end